gRPC method types
We can split these method types in two categories:
gRPC NuGet packages
Since May 2021, Microsoft has a series of packages for .NET to work with gRPC. These are Microsoft’s recommended implementation of gRPC for .NET.
- Grpc.AspNetCore for hosting a gRPC service in ASP.NET Core.
- Grpc.Net.Client for adding gRPC client support to any .NET project by building on HttpClient.
- Grpc.Net.ClientFactory for adding gRPC client support to any .NET code base by building on HttpClientFactory.(includes Grpc.Net.Client)
- Provides a central location for configuring logical gRPC client instances.
- Manages the lifetime of the underlying HttpClientMessageHandler.
- Automatic propagation of deadline and cancellation in an ASP.NET Core gRPC service.
THere are other packages available:
- Grpc.Tools nuget package which provides the codegen build integration for C# projects will continue to be supported (and will potentially get improvements) – as it’s used by both Grpc.Core and grpc-dotnet. This package is independent of C core.
- Grpc.Core.Api package is a prerequisite for grpc-dotnet so it will potentially evolve over time as well (but it’s a pure C# API only package and since it only contains the public API surface, changes are very infrequent)
The original gRPC C# implementation (the Grpc.Core nuget package) will enter maintenance mode and won’t be getting any new features and will only receive important bug fixes and security fixes going forward. Grpc.Net.Client and Grpc.AspNetCore.Server are the official implementations
Creating our first project
We will create a new gRPC project to see how it works.
- add a new project of type ASP.NET Core gRPC Service
- Let's have a look at the proto file
syntax = "proto3";
option csharp_namespace = "Basics";
package greet;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply);
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings.
message HelloReply {
string message = 1;
}
- Note that the gRPC proto file is marked to be used in the server side
<ItemGroup>
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>
- If you are using VS, click Show all files and under obj\Debug\net7.0\Protos folder, you will see the two class files named Greet.cs and GreetGrpc.cs. These are automatically generated from the greet.proto file
- In GreetGrpc.cs, note the Greeter.GreeterBase class that the GreeterService class inherited from. You do not need to understand how this base class is implemented.
If you clean a gRPC project, then you will lose the automatically generated types and see compile errors. To recreate them, simply make any change to a .proto file or close and reopen the project/solution.
The Grpc.Tools package generates the C# class files from the registered .proto files, and those class files use types defined in Google’s package to implement the serialization to the Protobuf serialization format. The Grpc.AspNetCore.Server. ClientFactory package includes both server-side and client-side support for gRPC in a .NET project.
- In Program.cs, in the section that configures services, note the call to add gRPC to the services
collection, as shown in the following code:
builder.Services.AddGrpc(); - In Program.cs, - configure the HTTP pipeline - call to map the Greeter service:
app.MapGrpcService<GreeterService>(); - Enable logging by adding in appsettings.json
Microsoft.AspNetCore": "Information". This will allow us to see our gRPC calls too. - Build the project.
Creating a consumer project
We will first create a client for our gRPC service and then move to implement the other methods.
- Add a Console App project, and name it Basics.Client
- Install some NuGet packages
- Google.Protobuf
- Grpc.Net.ClientFactory - this includes .Net.Client
- Grpc.Tools
- Make sure it behaves like a client Edit the .csproj file and add an item group
<ItemGroup>
<Protobuf Include="..\Basics\Protos\greet.protoo" GrpcServices="Client" />
</ItemGroup>
Point the Include to the proto file path. Usually adding a .. will do the trick, or simply copy the proto file in the project
Other ways to consume gRPC services
You can add a reference to a gRPC service by using the old Add Service Reference -> gRPC service Then you need to provide a path to the .proto files
Old approach vs the new one
The Grpc.Core usage
Channel channel = new Channel("localhost:5000", ChannelCredentials.Insecure);
var client = new Greeter.GreeterClient(channel);
vs
using var channel = GrpcChannel.ForAddress("https://localhost:5000");
var client = new Greeter.GreeterClient(channel);
Deadlines/Timeouts
With gRPC, clients have the ability to set a time limit for completing an RPC before it's terminated with a DEADLINE_EXCEEDED error. On the server side, the server can check if a particular RPC has timed out or how much time remains to finish the RPC.
The process of setting a deadline or timeout is specific to the language being used. Some language APIs use timeouts (a duration of time), while others use a deadline (a fixed point in time) and may or may not have a predefined deadline.
RPC termination
In gRPC, both the client and server make independent and local determinations of the success of the call, and their conclusions may not match. This means that, for example, you could have an RPC that finishes successfully on the server side (“I have sent all my responses!”) but fails on the client side (“The responses arrived after my deadline!”). It’s also possible for a server to decide to complete before a client has sent all its requests.
Cancelling an RPC
Either the client or the server can cancel an RPC at any time. A cancellation terminates the RPC immediately so that no further work is done.
Warning Changes made before a cancellation are not rolled back.
Using the generated client
Good Practice: The default is no deadline. Always set a deadline in the client call. In your service implementation, get the deadline and use it to automatically abandon the work if it is exceeded. Pass the cancellation token to any asynchronous calls so that work completes quickly on the server and frees up resources.
Tips & tricks
In case your classes are not generated, check the .csproj and make sure the item group is included
<ItemGroup>
<Protobuf Include="Protos\myproto.proto" GrpcServices="Server" />
</ItemGroup>